#ifndef TREE_H
#define TREE_H

#include <vector>
#include <string>
#include <iostream>
#include "token.h"
#include "types.h"

                /* Дерево виводу */

class TreeOutput
{
    TreeOutput *parent_node; // батьківський вузол
    TreeOutput *root_node; // вказує на корневий вузол (початок ф-ції)
    std::vector<TreeOutput*> child_nodes; // дочірні вузли
    TokenEntry token_entry;
    uint rules_counter; // лічильник правил - використовується при побудові дерева. Якщо counter == 0 - поточним вузлом дерева стає parent
    uint depth; // глубина розміщення даного вузла відносно корня дерева
public:
    TreeOutput(std::string n, int c)
        : token_entry(n), parent_node(0), rules_counter(c), root_node(0), depth(0) {}
    TreeOutput(std::string n, TokenType t, TreeOutput *p)
        : token_entry(n, t), parent_node(p), root_node(0), depth(0) {}
    TreeOutput(std::string n, TokenType t, int c)
        : token_entry(n, t), rules_counter(c), root_node(0), depth(0) {}
    TreeOutput(std::string n)
        : token_entry(n), parent_node(0), root_node(0), depth(0) {}
    TreeOutput()
        : parent_node(0), root_node(0), depth(0) {}
    TreeOutput(std::string n, TreeOutput *p)
        : token_entry(n), parent_node(p), root_node(0), depth(0) {}
    TreeOutput(std::string t_n, std::string r_n, TokenType t, TreeOutput *p)
        : token_entry(t_n, r_n, t), parent_node(p), root_node(0), depth(0) {}
    ~TreeOutput()
    {
        for (uint i = 0; i < child_nodes.size(); i++) delete child_nodes[i];
    }
    void insertOutputTree(TreeOutput *tree)
    {
        tree->parent_node = this;
        child_nodes.push_back(tree);
        --rules_counter;
    }
    void copyTreeOutput(TreeOutput*); // конструктор копій
    void setRulesCounter(uint c) {  rules_counter = c; }
    void setDepth(uint d) { depth = d; }
    void modifyRulesCounter(uint c) { rules_counter += c; }
    void setVarName(std::string n)
    {
        token_entry.real_name = n;
        token_entry.token_name = n;
    }
    void setNodeType(TokenType t) { token_entry.token_type = t; }
    void setRootNode(TreeOutput *r) { root_node = r; }
    TreeOutput *getRootNode() { return root_node; }
    std::vector<TreeOutput*> &getChildNodes() { return child_nodes; }
    std::string getNodeName() const { return token_entry.real_name; } // повертає справжнє ім'я токена(не граматичне)
    std::string getNodeGrammarName() const { return token_entry.token_name; } //  повертає граматичне ім'я токена
    TokenType getNodeType() const { return token_entry.token_type; }
    uint getRulesCounter() const { return rules_counter; }
    uint getDepth() const { return depth; }
    TreeOutput *getParentNode() { return parent_node; }
    void setParentNode(TreeOutput *p) { parent_node = p; }
};

#endif // TREE_H
